package com.maiji.cloud.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.maiji.cloud.entities.community.ComComment;
import com.maiji.cloud.mapper.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.maiji.cloud.entities.login.AppUser;
import com.maiji.cloud.entities.login.ArticleCollectEntity;
import com.maiji.cloud.entities.login.ArticleCommentEntity;
import com.maiji.cloud.entities.login.ArticlePraiseLogEntity;
import com.maiji.cloud.entities.login.ArticleTranspondLogEntity;
import com.maiji.cloud.entities.login.MaijiArticle;
import com.maiji.cloud.entities.login.UploadRecord;
import com.maiji.cloud.entities.login.UserInfo;
import com.maiji.cloud.request.BaseDataReqDto;
import com.maiji.cloud.request.ReqMetaData;
import com.maiji.cloud.request.login.ArticleCommentReqData;
import com.maiji.cloud.response.BaseDataResDto;
import com.maiji.cloud.response.BaseMetaResDto;
import com.maiji.cloud.response.BaseResDto;
import com.maiji.cloud.response.ResMetaData;
import com.maiji.cloud.response.Status;
import com.maiji.cloud.response.login.ArticleCommentListResData;
import com.maiji.cloud.response.login.IsPraiseOrCollectResData;
import com.maiji.cloud.response.login.UploadImageResData;
import com.maiji.cloud.response.login.UserInfoResData;
import com.maiji.cloud.service.AppUserService;
import com.maiji.cloud.service.ArticleCollectService;
import com.maiji.cloud.service.ArticleCommentService;
import com.maiji.cloud.service.ArticlePraiseLogService;
import com.maiji.cloud.service.ArticleService;
import com.maiji.cloud.service.MaijiArticleService;
import com.maiji.cloud.service.UploadRecordService;
import com.maiji.cloud.utils.BaseService;
import com.maiji.cloud.utils.CommonIntValueEnum;
import com.maiji.cloud.utils.UUID_MD5;

@Service
@Transactional
public class ArticleServiceImpl extends ServiceImpl<MaijiArticleMapper, MaijiArticle> implements ArticleService {

	private static final Logger logger = LoggerFactory.getLogger(ArticleServiceImpl.class);
    @Value("${domain.name}")
    private String realName;
	@Autowired
	private ArticlePraiseLogMapper articlePraiseLogMapper;
	@Autowired
	private AppUserService appUserService;
	@Autowired
	private ArticleTranspondLogMapper articleTranspondLogMapper;
	@Autowired
	private ArticleCommentMapper articleCommentMapper;
	@Autowired
	private ArticleCommentService articleCommentService;
	@Autowired
	private UserInfoMapper userInfoMapper;
	@Autowired
	private ArticleCollectMapper articleCollectMapper;
	@Autowired
	private MaijiArticleService maijiArticleService;
	@Autowired
    private UploadRecordService uploadRecordService;
	@Autowired
	private ArticleCollectService  articleCollectService;
	@Autowired
	private ArticlePraiseLogService articlePraiseLogService;

	@Override
	public BaseResDto articlePraise(BaseDataReqDto<String> param, String token) {
		logger.info("ArticleServiceImpl.articlePraise param is {},token is {}", JSON.toJSONString(param), token);
		if (StringUtils.isBlank(param.getData()))
			return new BaseResDto(Status.PARAMETERERROR, "token 为空 ");
		// 获得用户id
		AppUser appUser = appUserService.checkToken(token);
		if (appUser == null) {
			logger.info("ArticleServiceImpl.articlePraise,appUser is {}", JSON.toJSONString(appUser));
			return new BaseResDto(Status.PARAMETERERROR, "token 无效 ");
		}
		ArticlePraiseLogEntity articlePraiseLogEntity = articlePraiseLogMapper.selectOne(new ArticlePraiseLogEntity().setArticleId(param.getData()).setUserId(appUser.getUuId())); 
		if(articlePraiseLogEntity != null) return new BaseResDto(Status.SUCCESS);
		
		articlePraiseLogEntity = new ArticlePraiseLogEntity().setUuId(UUID_MD5.getUUID())
				.setArticleId(param.getData()).setUserId(appUser.getUuId()).setInTime(new Date());

		articlePraiseLogMapper.insert(articlePraiseLogEntity);

		return new BaseResDto(Status.SUCCESS);
	}

	@Override
	public BaseResDto articleTranspond(BaseDataReqDto<String> param, String token) {
		logger.info("ArticleServiceImpl.articleTranspond param is {},token is {}", JSON.toJSONString(param), token);
		if (StringUtils.isBlank(param.getData()))
			return new BaseResDto(Status.PARAMETERERROR, "token 为空 ");
		// 获得用户id
		AppUser appUser = appUserService.checkToken(token);
		if (appUser == null) {
			logger.info("ArticleServiceImpl.articleTranspond,appUser is {}", JSON.toJSONString(appUser));
			return new BaseResDto(Status.PARAMETERERROR, "token 无效 ");
		}

		ArticleTranspondLogEntity articleTranspondLogEntity = new ArticleTranspondLogEntity()
				.setUuId(UUID_MD5.getUUID()).setArticleId(param.getData()).setUserId(appUser.getUuId())
				.setInTime(new Date());

		articleTranspondLogMapper.insert(articleTranspondLogEntity);

		return new BaseResDto(Status.SUCCESS);
	}

	@Override
	public BaseResDto articleComment(BaseDataReqDto<ArticleCommentReqData> param, String token) {
		logger.info("ArticleServiceImpl.articleComment param is {},token is {}", JSON.toJSONString(param), token);
		// 获得用户id
		AppUser appUser = appUserService.checkToken(token);
		if (appUser == null) {
			logger.info("ArticleServiceImpl.articleComment,appUser is {}", JSON.toJSONString(appUser));
			return new BaseResDto(Status.PARAMETERERROR, "token 无效 ");
		}

		ArticleCommentEntity articleCommentEntity = new ArticleCommentEntity().setUuId(UUID_MD5.getUUID())
				.setArticleId(param.getData().getArticleId()).setSourceUserId(appUser.getUuId())
				.setType(param.getData().getType()).setBelongId(param.getData().getArticleId())
                .setInTime(new Date()).setContent(param.getData().getContent());

		if (param.getData().getType() == CommonIntValueEnum.ARTICLE_COMMENT_REVERT.getValue()
				&& StringUtils.isNotBlank(param.getData().getCommentId())) {
			ArticleCommentEntity newArticleCommentEntity = articleCommentMapper
					.selectById(param.getData().getCommentId());
			if (newArticleCommentEntity.getType() != CommonIntValueEnum.ARTICLE_COMMENT.getValue())
				articleCommentEntity.setType(CommonIntValueEnum.ARTICLE_COMMENT_TO_COMMENT.getValue());
			if(newArticleCommentEntity.getType() == CommonIntValueEnum.ARTICLE_COMMENT.getValue()) {
				articleCommentEntity.setBelongId(newArticleCommentEntity.getUuId());
			}else {
				articleCommentEntity.setBelongId(newArticleCommentEntity.getBelongId());
			}
			articleCommentEntity.setArticleId(newArticleCommentEntity.getArticleId());
			articleCommentEntity.setTargetUserId(newArticleCommentEntity.getSourceUserId());
		}

		articleCommentMapper.insert(articleCommentEntity);

		return new BaseResDto(Status.SUCCESS);
	}

	@Override
	public BaseMetaResDto<List<ArticleCommentListResData>> getArticleCommentList(BaseDataReqDto<String> param) {
		logger.info("ArticleServiceImpl.getArticleCommentList param is {}", JSON.toJSONString(param));

		EntityWrapper<ArticleCommentEntity> entityWrapper = new EntityWrapper<ArticleCommentEntity>();
		entityWrapper.eq("type", CommonIntValueEnum.ARTICLE_COMMENT.getValue());
		entityWrapper.eq("article_id", param.getData());
		entityWrapper.orderBy("in_time", false);
		entityWrapper.eq("is_del", CommonIntValueEnum.ARTICLE_COMMENT_IS_DEL_FALSE.getValue());
		
		
		Page<ArticleCommentEntity> pageArticleCommentEntity = articleCommentService.selectPage(new Page<>(param.getMetaData().getPage(), param.getMetaData().getSize()), entityWrapper);
		List<ArticleCommentEntity> listArticleCommentEntity = pageArticleCommentEntity.getRecords();
		
		
		Map<String, List<ArticleCommentEntity>> commentToComment = articleCommentService.selectList(new EntityWrapper<ArticleCommentEntity>().eq("article_id", param.getData()).ne("type", CommonIntValueEnum.ARTICLE_COMMENT.getValue()))
                .parallelStream().collect(Collectors.groupingBy(ArticleCommentEntity::getBelongId));
		
		List<ArticleCommentListResData> listArticleCommentListResData = listArticleCommentEntity.parallelStream()
				.map(articleCommentEntity -> {
					ArticleCommentListResData articleCommentListResData = new ArticleCommentListResData();
					BeanUtils.copyProperties(articleCommentEntity, articleCommentListResData);
					articleCommentListResData.setCommentId(articleCommentEntity.getUuId());
					
					int count = commentToComment.get(articleCommentEntity.getUuId()) == null ? 0 : commentToComment.get(articleCommentEntity.getUuId()).size();
					articleCommentListResData.setReplySumCount(count);
					//用户信息
					UserInfo userInfo = userInfoMapper.selectOneByUserId(articleCommentEntity.getSourceUserId());
					
					UserInfoResData UserInfoResData = new UserInfoResData();
					BeanUtils.copyProperties(userInfo, UserInfoResData);
					articleCommentListResData.setSourceUser(UserInfoResData);
					
					//根据评论的信息获得评论的恢复
					BaseMetaResDto<List<ArticleCommentListResData>> res = getArticleCommentReply(new BaseDataReqDto<String>().setData(articleCommentEntity.getUuId()).setMetaData(new ReqMetaData().setPage(1).setSize(3)));
					articleCommentListResData.setList(res.getData());
					
					return articleCommentListResData;
				}).collect(Collectors.toList());
		ResMetaData resMetaData = new ResMetaData(pageArticleCommentEntity.getCurrent(), pageArticleCommentEntity.getSize(), pageArticleCommentEntity.getTotal());
		return new BaseMetaResDto<List<ArticleCommentListResData>>().setData(listArticleCommentListResData).setResMetaData(resMetaData);
	}

	@Override
	public BaseMetaResDto<List<ArticleCommentListResData>> getArticleCommentReply(BaseDataReqDto<String> param) {
		logger.info("ArticleServiceImpl.getArticleCommentReply param is {}", JSON.toJSONString(param));
		
		EntityWrapper<ArticleCommentEntity> entityWrapper = new EntityWrapper<ArticleCommentEntity>();
		entityWrapper.ne("type", CommonIntValueEnum.ARTICLE_COMMENT.getValue());
		entityWrapper.eq("belong_id", param.getData());
		entityWrapper.orderBy("in_time", false);
		entityWrapper.eq("is_del", CommonIntValueEnum.ARTICLE_COMMENT_IS_DEL_FALSE.getValue());
		Page<ArticleCommentEntity> pageArticleCommentEntity = articleCommentService.selectPage(new Page<>(param.getMetaData().getPage(), param.getMetaData().getSize()), entityWrapper);
		
		List<ArticleCommentEntity> listArticleCommentEntity = pageArticleCommentEntity.getRecords();
		
		//发起评论的用户ID集合
		List<String> sourceUserIds =  listArticleCommentEntity.stream().map(
				articleCommentEntity -> articleCommentEntity.getSourceUserId()
		).collect(Collectors.toList());
		
		//被回复的评论集合
		List<String> targetUserIds =  listArticleCommentEntity.stream().map(
				articleCommentEntity -> articleCommentEntity.getTargetUserId()
		).collect(Collectors.toList());
		
		List<UserInfoResData> sourceUserInfo = userInfoMapper.selectList(new EntityWrapper<UserInfo>().in("user_id", sourceUserIds)).parallelStream()
				.map(userInfo -> {
					UserInfoResData userInfoResData = new UserInfoResData();
					BeanUtils.copyProperties(userInfo, userInfoResData);
					return userInfoResData;
				}).collect(Collectors.toList());
		
		List<UserInfoResData> targetUserInfo = userInfoMapper.selectList(new EntityWrapper<UserInfo>().in("user_id", targetUserIds)).parallelStream()
				.map(userInfo -> {
					UserInfoResData userInfoResData = new UserInfoResData();
					BeanUtils.copyProperties(userInfo, userInfoResData);
					return userInfoResData;
				}).collect(Collectors.toList());
		
		
		 Map<String, UserInfoResData> sourceUserInfoMap = sourceUserInfo.parallelStream()
                 .collect(Collectors.toMap(UserInfoResData::getUserId, UserInfoResData::getThis));
		 
		 Map<String, UserInfoResData> targetUserInfoMap = targetUserInfo.parallelStream()
                 .collect(Collectors.toMap(UserInfoResData::getUserId, UserInfoResData::getThis));
		 
		 List<ArticleCommentListResData> list  = listArticleCommentEntity.parallelStream()
					.map(articleCommentEntity -> {
						ArticleCommentListResData articleCommentListResData = new ArticleCommentListResData();
						BeanUtils.copyProperties(articleCommentEntity, articleCommentListResData);
						articleCommentListResData.setSourceUser(sourceUserInfoMap.get(articleCommentEntity.getSourceUserId()));
						articleCommentListResData.setTargetUser(targetUserInfoMap.get(articleCommentEntity.getTargetUserId()));
						return articleCommentListResData;
					}).collect(Collectors.toList());
			
		 
		 ResMetaData resMetaData = new ResMetaData(pageArticleCommentEntity.getCurrent(), pageArticleCommentEntity.getSize(), pageArticleCommentEntity.getTotal());
		return new BaseMetaResDto<List<ArticleCommentListResData>>(Status.SUCCESS).setData(list).setResMetaData(resMetaData);
	}

	@Override
	public BaseResDto cancelArticlePraise(BaseDataReqDto<String> param, String token) {
		logger.info("ArticleServiceImpl.cancelArticlePraise param is {},token is {}", JSON.toJSONString(param), token);
		// 获得用户id
		AppUser appUser = appUserService.checkToken(token);
		if (appUser == null) {
			logger.info("ArticleServiceImpl.cancelArticlePraise,appUser is {}", JSON.toJSONString(appUser));
			return new BaseResDto(Status.PARAMETERERROR, "token 无效 ");
		}
		
		ArticlePraiseLogEntity articlePraiseLogEntity = articlePraiseLogMapper.selectOne(new ArticlePraiseLogEntity().setArticleId(param.getData()).setUserId(appUser.getUuId()));
		if(articlePraiseLogEntity == null) return new BaseResDto(Status.PARAMETERERROR);
		articlePraiseLogMapper.deleteById(articlePraiseLogEntity.getUuId());
		
		return new BaseResDto(Status.SUCCESS);
	}

	@Override
	public BaseResDto deleteArticleComment(BaseDataReqDto<String> param, String userId) {
		ArticleCommentEntity articleCommentEntity = articleCommentMapper.selectById(param.getData());
		//APP用户不能随意删除，只能删除别人给自己评论的
		if(articleCommentEntity == null || ! articleCommentEntity.getSourceUserId().equals(userId)) return new BaseResDto(Status.PARAMETERERROR);
		articleCommentEntity.setIsDel(CommonIntValueEnum.ARTICLE_COMMENT_IS_DEL_TRUE.getValue());
		articleCommentEntity.setOperationId(userId);
		articleCommentMapper.updateById(articleCommentEntity);
		return new BaseResDto(Status.SUCCESS);
	}

	@Override
	public BaseDataResDto<IsPraiseOrCollectResData> isPraise(String articleId, String userId) {
		if(StringUtils.isBlank(articleId) || StringUtils.isBlank(userId)){
			logger.info("ArticleServiceImpl.isPraise articleId is {},userId is {}", articleId,userId);
			return new BaseDataResDto<IsPraiseOrCollectResData>(Status.PARAMETERERROR);
		}
		
		IsPraiseOrCollectResData isPraiseOrCollectResData = new IsPraiseOrCollectResData(); 
		
		Boolean isPraise = false;
		Boolean isCollect = false;
		
		ArticlePraiseLogEntity articlePraiseLogEntity = articlePraiseLogMapper.selectOne(new ArticlePraiseLogEntity().setUserId(userId).setArticleId(articleId) );
		if(articlePraiseLogEntity != null) isPraise = true;
		
		ArticleCollectEntity articleCollectEntity = articleCollectMapper.selectOne(new ArticleCollectEntity().setArticleId(articleId).setUserId(userId)); 
		if(articleCollectEntity != null) isCollect = true;
		
		isPraiseOrCollectResData.setIsCollect(isCollect);
		isPraiseOrCollectResData.setIsPraise(isPraise);
		
		return new BaseDataResDto<IsPraiseOrCollectResData>(Status.SUCCESS).setData(isPraiseOrCollectResData);
	}

	@Override
	public BaseResDto articleCollect(String articleId, String userId) {
		if(StringUtils.isBlank(articleId) || StringUtils.isBlank(userId)){
			logger.info("ArticleServiceImpl.articleCollect articleId is {},userId is {}", articleId,userId);
			return new BaseDataResDto<Boolean>(Status.PARAMETERERROR);
		}
		
		ArticleCollectEntity articleCollectEntity = articleCollectMapper.selectOne(new ArticleCollectEntity().setArticleId(articleId).setUserId(userId)); 
		if(articleCollectEntity != null) return new BaseResDto(Status.SUCCESS);
		
		articleCollectEntity = new ArticleCollectEntity().setUuId(UUID_MD5.getUUID())
				.setArticleId(articleId).setUserId(userId).setInTime(new Date());

		articleCollectMapper.insert(articleCollectEntity);

		return new BaseResDto(Status.SUCCESS);
	}

	@Override
	public BaseResDto cancelArticleCollect(String articleId, String userId) {
		if(StringUtils.isBlank(articleId)){
            if (! articleCollectService.delete(new EntityWrapper<ArticleCollectEntity>().eq("user_id", userId)))
                return new BaseResDto(Status.ERROR.setMessage("清空文章收藏列表失败"));
		} else {
            ArticleCollectEntity articleCollectEntity = articleCollectMapper.selectOne(new ArticleCollectEntity().setArticleId(articleId).setUserId(userId));
            if(articleCollectEntity == null) return new BaseResDto(Status.PARAMETERERROR);
            articleCollectMapper.deleteById(articleCollectEntity.getUuId());
        }
		return new BaseResDto(Status.SUCCESS);
	}

	@Override
	public BaseDataResDto<List<MaijiArticle>> articleCollectList(BaseDataReqDto<String> param) {
		if( StringUtils.isBlank(param.getData())){
			logger.info("ArticleServiceImpl.articleCollectList ,param is {}",JSON.toJSONString(param));
			return new BaseDataResDto<List<MaijiArticle>>(Status.PARAMETERERROR);
		}
		EntityWrapper<ArticleCollectEntity> entityWrapper = new EntityWrapper<ArticleCollectEntity>();
		entityWrapper.eq("user_id", param.getData());
		entityWrapper.orderBy("in_time", false);
        ReqMetaData metaData = param.getMetaData();
        Page<ArticleCollectEntity> page = articleCollectService.selectPage(new Page<>(metaData.getPage(), metaData.getSize()), entityWrapper);
		List<ArticleCollectEntity> listArticleCollectEntity = page.getRecords();
		List<String> articleIds = listArticleCollectEntity.parallelStream().map(ArticleCollectEntity::getArticleId).collect(Collectors.toList());
        List<MaijiArticle> list = Lists.newArrayList();
        if (articleIds.size() > 0) {
		    list = maijiArticleService.selectBatchIds(articleIds).parallelStream().map(a -> a.setRealName(realName)).collect(Collectors.toList());
            Wrapper<UploadRecord> recordWrapper = new EntityWrapper<UploadRecord>().in("belong_id", articleIds).eq("is_main", 1);
            List<UploadRecord> uploadRecords = uploadRecordService.selectList(recordWrapper);
            if (uploadRecords.size() > 0) list = BaseService.dealWithOneToOne(list, "getUuId", MaijiArticle.class,
                    "setImg", uploadRecords, "getBelongId", UploadImageResData.class);
        }
		return new BaseDataResDto<List<MaijiArticle>>(Status.SUCCESS).setData(list);
	}

	@Override
	public BaseMetaResDto<List<UserInfoResData>> getArticlePraiseList(BaseDataReqDto<String> param) {
		logger.info("ArticleServiceImpl.getArticlePraiseList param is {}", JSON.toJSONString(param));
		BaseMetaResDto<List<UserInfoResData>> res = new BaseMetaResDto<List<UserInfoResData>>(Status.SUCCESS);
		if( StringUtils.isBlank(param.getData())){
			logger.info("ArticleServiceImpl.getArticlePraiseList ,param is {}",JSON.toJSONString(param));
			return new BaseMetaResDto<List<UserInfoResData>>(Status.PARAMETERERROR);
		}
		EntityWrapper<ArticlePraiseLogEntity> entityWrapper = new EntityWrapper<ArticlePraiseLogEntity>();
		entityWrapper.eq("article_id", param.getData());
		entityWrapper.orderBy("in_time", false);
		
		Page<ArticlePraiseLogEntity> pageArticlePraiseLogEntity = articlePraiseLogService.selectPage(new Page<>(param.getMetaData().getPage(), param.getMetaData().getSize()), entityWrapper);
		List<ArticlePraiseLogEntity> listArticlePraiseLogEntity = pageArticlePraiseLogEntity.getRecords();
		
		List<String> userIds =  listArticlePraiseLogEntity.stream().map(
				articlePraiseLogEntity -> articlePraiseLogEntity.getUserId()
		).collect(Collectors.toList());
		if(userIds != null && userIds.size() > 0 ) {
			List<UserInfoResData> listUserInfo = userInfoMapper.selectList(new EntityWrapper<UserInfo>().in("user_id", userIds)).parallelStream()
					.map(userInfo -> {
						UserInfoResData userInfoResData = new UserInfoResData();
						BeanUtils.copyProperties(userInfo, userInfoResData);
						return userInfoResData;
					}).collect(Collectors.toList());
			res.setData(listUserInfo);
		}
		
		 ResMetaData resMetaData = new ResMetaData(pageArticlePraiseLogEntity.getCurrent(), pageArticlePraiseLogEntity.getSize(), pageArticlePraiseLogEntity.getTotal());
		return res.setResMetaData(resMetaData);
	}

    @Override
    public BaseDataResDto<MaijiArticle> findMaijiArticleById(String articleId) {
        MaijiArticle maijiArticle = selectById(articleId);
        if (maijiArticle == null) return new BaseDataResDto<>(Status.PARAMETERERROR);
        EntityWrapper<UploadRecord> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("belong_id", articleId);
        entityWrapper.eq("is_main", 1);
        UploadRecord uploadRecord = uploadRecordService.selectOne(entityWrapper);
        UploadImageResData img = new UploadImageResData();
        BeanUtils.copyProperties(uploadRecord, img);
        return new BaseDataResDto<MaijiArticle>(Status.SUCCESS).setData(maijiArticle.setImg(img));
    }

}
